package com.googlecode.connectlet.machine;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.AlgorithmParameterGenerator;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

import javax.crypto.Cipher;

import com.googlecode.connectlet.crypto.KeyImpl;
import com.googlecode.connectlet.crypto.ProviderFactory;
import com.googlecode.connectlet.machine.engine.MachineEngine;
import com.googlecode.connectlet.machine.provider.MachineConnection;
import com.googlecode.connectlet.machine.provider.MachineKey;
import com.googlecode.connectlet.machine.provider.MachineProvider;
import com.googlecode.connectlet.machine.provider.cipher.MachineCbcCipher;
import com.googlecode.connectlet.machine.provider.cipher.MachineRSACipher;
import com.googlecode.connectlet.machine.provider.key.MachineKeyWithSize;
import com.googlecode.connectlet.machine.provider.key.MachinePrivateKey;

public class TestMachine {
	private static final char[] KEYSTORE_PASSWORD = "changeit".toCharArray();

	public static void main(String[] args) throws Exception {
		Certificate cert = CertificateFactory.getInstance("X509").generateCertificate(new FileInputStream("D:\\CA.CER"));

		MachineEngine.startServer();
		Thread.sleep(1000);

		MachineConnection conn = new MachineConnection("localhost", 8341);

		AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.
				getInstance("Machine", MachineProvider.getInstance());
		paramGen.init(conn);

		MachineKey machineKey = paramGen.generateParameters().
				getParameterSpec(MachineKey.class);
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", MachineProvider.getInstance());
		keyPairGen.initialize(new MachineKeyWithSize(machineKey, 2048));
		// KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		// keyPairGen.initialize(2048);
		KeyPair keyPair = keyPairGen.generateKeyPair();
		// keyPair = new KeyPair(keyPair.getPublic(), machineKey.generatePrivate((RSAPrivateCrtKey) keyPair.getPrivate()));

		KeyStore keyStore = KeyStore.getInstance("Machine", MachineProvider.getInstance());
		keyStore.load(null, null);
		keyStore.setKeyEntry("", keyPair.getPrivate(), KEYSTORE_PASSWORD, new Certificate[] {cert});
		FileOutputStream out = new FileOutputStream("D:\\KEYSTORE.DAT");
		keyStore.store(out, KEYSTORE_PASSWORD);
		out.close();
		FileInputStream in = new FileInputStream("D:\\KEYSTORE.DAT");
		keyStore.load(in, KEYSTORE_PASSWORD);
		in.close();
		MachinePrivateKey privateKey = (MachinePrivateKey) keyStore.getKey("", KEYSTORE_PASSWORD);

		Signature signature = Signature.getInstance("MD5withRSA", MachineProvider.getInstance());
		signature.setParameter(machineKey);
		signature.initSign(privateKey);
		signature.update("0123456789ABCDEF".getBytes());
		byte[] result = signature.sign();

		signature = Signature.getInstance("MD5withRSA");
		signature.initVerify(keyPair.getPublic());
		signature.update("0123456789ABCDEF".getBytes());
		System.out.println(signature.verify(result));

		Cipher rsa = Cipher.getInstance("RSA");
		rsa.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
		byte[] cipher = rsa.doFinal("0123456789ABCDEF".getBytes());
		rsa = ProviderFactory.generateCipher(new MachineRSACipher());
		rsa.init(Cipher.DECRYPT_MODE, privateKey, machineKey);
		System.out.write(rsa.doFinal(cipher));
		System.out.println();

		KeyImpl key = new KeyImpl("0123456789ABCDEF".getBytes());
		Cipher cbc = ProviderFactory.generateCipher(new MachineCbcCipher());
		cbc.init(Cipher.ENCRYPT_MODE, key, machineKey);
		cipher = cbc.doFinal("0123456789ABCDEF".getBytes());
		cbc.init(Cipher.DECRYPT_MODE, key, machineKey);
		System.out.write(cbc.doFinal(cipher));
		System.out.println();

		machineKey.destory();

		MachineEngine.stopServer();
	}
}